﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using Microsoft.ServiceBus;
using nwrole.lib;
using nwrole.toolbox.sync.ServiceHost;
using nwrole.toolbox.sync.contract;
using nwrole.toolbox.sync.entity;

namespace nwrole.toolbox.sync.client
{
    public class SyncDestinationServiceClient
    {
        private ServiceConnectionInfo connInfo;

        public SyncDestinationServiceClient(ServiceConnectionInfo connectionInfo)
        {
            connInfo = connectionInfo;
        }

        public SyncMessageEnvelope SyncComplete(SyncCompleteEnvelope command)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.SyncComplete(command);

            serviceChannel.Close();
            return result;
        }

        public SyncMessageEnvelope ProcessMessage(SyncCommandEnvelope command)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.ProcessMessage(command);

            serviceChannel.Close();
            return result;
        }

        public void ProcessMessageOld(SyncMessageEnvelope message)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            serviceChannel.ProcessMessageOld(message);

            serviceChannel.Close();
        }

        public List<IntMessageRow> GetFailedMessageRows(long messageId)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.GetFailedMessageRows(messageId);

            serviceChannel.Close();
            return result;
        }

        public List<IntMessage> GetFailedMessages()
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.GetFailedMessages();

            serviceChannel.Close();
            return result;
        }

        public IntMessage GetMessage(long messageId)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.GetMessage(messageId);

            serviceChannel.Close();
            return result;
        }

        public Result DeleteOldRowsFromDestinationTable(SyncEntity syncEntity)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.DeleteOldRowsFromDestinationTable(syncEntity);

            serviceChannel.Close();
            return result;
        }

        public bool DeployDestination(SyncEntity syncEntity)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.DeployDestination(syncEntity);

            serviceChannel.Close();
            return result;
        }

        public bool DeployDestEnvironment()
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            var result = serviceChannel.DeployDestEnvironment();

            serviceChannel.Close();
            return result;
        }

        public void InitFileTransfer(Guid fileId, long totalBytes, string destPath)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            serviceChannel.InitFileTransfer(fileId, totalBytes, destPath);

            serviceChannel.Close();
        }

        public void SendFilePart(Guid fileId, long offset, long bytes, byte[] data)
        {
            ISyncDestinationServiceChannel serviceChannel = GetChannel();
            serviceChannel.Open();

            serviceChannel.SendFilePart(fileId, offset, bytes, data);

            serviceChannel.Close();
        }

        private ISyncDestinationServiceChannel GetChannel()
        {
            if (connInfo.Type == ServiceConnectionInfo.ServiceConnectionType.WebService)
                return GetChannelWebService();

            return GetChannelServiceBus();
        }

        private ISyncDestinationServiceChannel GetChannelServiceBus()
        {
            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

            Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", connInfo.ServiceBusServiceNamespace, connInfo.ServiceBusServicePath);

            Console.WriteLine("Connecting to {0} address: {1}", "MyName", serviceUri);


            TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();

            sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(connInfo.ServiceBusIssuerName, connInfo.ServiceBusIssuerSecret);

            ChannelFactory<ISyncDestinationServiceChannel> channelFactory = new ChannelFactory<ISyncDestinationServiceChannel>();
            channelFactory.Endpoint.Address = new EndpointAddress(serviceUri);

            NetTcpRelayBinding binding = new NetTcpRelayBinding();
            //binding.ReceiveTimeout = new TimeSpan(0, 0, 120);
            binding.MaxConnections = 100;
            binding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            binding.MaxReceivedMessageSize = 2000000;
            binding.MaxBufferPoolSize = 2000000;
            binding.ReaderQuotas.MaxStringContentLength = 2000000;
            binding.ReaderQuotas.MaxArrayLength = 2000000;

            binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            binding.SendTimeout = new TimeSpan(0, 10, 0);

            channelFactory.Endpoint.Binding = binding;

            channelFactory.Endpoint.Contract.ContractType = typeof(ISyncDestinationServiceChannel);

            channelFactory.Endpoint.Behaviors.Add(sharedSecretServiceBusCredential);

            ISyncDestinationServiceChannel serviceChannel = channelFactory.CreateChannel();

            return serviceChannel;
        }

        private ISyncDestinationServiceChannel GetChannelWebService()
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            binding.SendTimeout = new TimeSpan(0, 10, 0);
            EndpointAddress ep = new EndpointAddress("http://" + connInfo.WebServiceBaseAddress + connInfo.WebServiceAddress);
            ISyncDestinationServiceChannel destinationService = ChannelFactory<ISyncDestinationServiceChannel>.CreateChannel(binding, ep);
            return destinationService;


            /*NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
            //binding.MaxReceivedMessageSize = 2000000;
            //binding.MaxBufferPoolSize = 2000000;

            binding.ReceiveTimeout = new TimeSpan(0, 0, 120);
            binding.MaxConnections = 100;
            binding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            binding.MaxReceivedMessageSize = 2000000;
            binding.MaxBufferPoolSize = 2000000;
            binding.ReaderQuotas.MaxStringContentLength = 2000000;
            binding.ReaderQuotas.MaxArrayLength = 2000000;

            binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
            binding.SendTimeout = new TimeSpan(0, 10, 0);

            //ChannelFactory<ISyncSourceServiceChannel> httpFactory = new ChannelFactory<ISyncSourceServiceChannel>(binding, new EndpointAddress("net.tcp://localhost:8086/JFTestService"));
            //ChannelFactory<ISyncSourceServiceChannel> httpFactory = new ChannelFactory<ISyncSourceServiceChannel>(binding, new EndpointAddress("net.tcp://" + localServicePath));
            ChannelFactory<ISyncDestinationServiceChannel> httpFactory = new ChannelFactory<ISyncDestinationServiceChannel>(binding, new EndpointAddress("net.tcp://" + connInfo.WebServiceBaseAddress + connInfo.WebServiceAddress));

            // DuplexChannelFactory<IRemoteWebContract> httpFactory = new DuplexChannelFactory<IRemoteWebContract>(callback, new NetTcpBinding(SecurityMode.None), new EndpointAddress("net.tcp://localhost:8083/RemoteService"));
            //DuplexChannelFactory<IRemoteWebContract> httpFactory = new DuplexChannelFactory<IRemoteWebContract>(callback, new NetNamedPipeBinding(), 
            //                                    new EndpointAddress("net.pipe://localhost/RemoteService"));
            return httpFactory.CreateChannel();*/
        }
    }
}
